07Security Research · Web3

Crypto Wallet Vulnerability —
Pending Tx Spoofing & Drop-Replace Exploit

Identified and demonstrated a critical exception-handling flaw in a major ERC-20 wallet provider. By sending a real ERC-20 transfer with an artificially low gas fee, the wallet showed the amount as received before the transaction confirmed — then a drop-and-replace attack silently cancelled it, yet the wallet still marked it as confirmed. Disclosed responsibly.

ERC-20
On-chain exploit
2
Transactions used
18d
Time to patch
Responsibly disclosed
The Vulnerability

A real transaction that looked confirmed before it was

ERC-20 transfers on Ethereum require a gas fee — the higher the fee, the faster miners pick up the transaction. By sending a legitimate ERC-20 transfer via Web3 APIs with an artificially low gas price, the transaction entered the mempool but took an extremely long time to actually be mined and confirmed.

The wallet provider's critical mistake: it displayed the pending amount in the recipient's balance immediately — before the transaction was confirmed. To the recipient, the funds had arrived. In reality, the transaction could still fail, be stuck, or be replaced.

Overall balance after exploit
Fake transaction details showing received
The Drop-and-Replace Attack

Taking it further with nonce replacement

Ethereum transactions include a nonce — a sequential counter per sender. Broadcasting a second transaction with the same nonce but a higher gas fee causes miners to drop the original and process the replacement instead. This is the standard "replace-by-fee" (RBF) mechanism.

By sending the replacement transaction — a tiny or zero-value transfer — the large original was silently cancelled on-chain. The wallet provider did not handle this exception. Instead of updating the status to "Dropped" or "Replaced", it left the original transaction marked as confirmed. The recipient's wallet showed the full amount as successfully received. The funds were never transferred.

Fake transaction flow
Technical Analysis

Two bugs, one working exploit

Bug 01
Optimistic Balance Display

The wallet credited the recipient's displayed balance as soon as a pending ERC-20 transfer was detected in the mempool — before any on-chain confirmation. This is the first and fundamental flaw that makes the attack possible.

Bug 02
Unhandled Drop-and-Replace Exception

When the original transaction was replaced via a higher-gas same-nonce broadcast, the wallet's transaction status listener did not catch the replaced or dropped state — leaving the original shown as "Confirmed".

Attack Sequence
Low Gas → Show → Replace → Confirmed

① Send large ERC-20 tx with very low gas → ② Recipient's wallet shows funds as arrived → ③ Broadcast same-nonce tx with high gas for tiny amount → ④ Original is dropped on-chain, wallet shows it as confirmed anyway.

Disclosure
Responsible Process

Full PoC written in Web3.js — both transactions scripted, reproducible on mainnet. Full technical report sent to the provider's security team. No public disclosure until patched — 18 days after report.

Tools Used

Research environment

Web3.jsERC-20Ethereum MempoolReplace-by-FeeNonce ManipulationSecurity ResearchResponsible Disclosure
Transaction Details
Overall Balance
Outcome

Why this matters

Root causeOptimistic UI
Attack requires internet access onlyYes
Time to patch (after disclosure)18 days
TakeawayNever trust pending
Interested in working
together?
Get in touch